#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include "server.h"


typedef struct
{
   unsigned char locker;
   unsigned char flag;
   sem_t sem1;
   sem_t sem2;
   void *pData;
   //unsigned char data_pool[4000];
}PKDATA_t;

//volatile PKDATA_t *pkdata;
pthread_mutex_t lock;


#if 0
int DiffMechWirte(void *handle, int idx, char *pbuffer, int size)
{
    PKDATA_t *pkdata = (PKDATA_t*)handle;
    sem_wait(&pkdata[idx].sem1);
    pkdata[idx].locker = 0x1;
    pkdata[idx].pData = malloc(size);
    
    memcpy((void *)pkdata[idx].pData, (void *)pbuffer, size);
    pkdata[idx].flag = 0x1;
    pkdata[idx].locker = 0x0;
    sem_post(&pkdata[idx].sem2);
    //printf("[DIFF-MECH] WRITE idx%d--------size=%d,      [%p]\r\n", idx, size, handle);
    return size;
}

int DiffMechRead(void *handle, int idx, char *pbuffer, int size)
{
    PKDATA_t *pkdata = (PKDATA_t*)handle;
    sem_wait(&pkdata[idx].sem2);
    //printf("[DIFF-MECH] READ idx%d--------size=%d [%p]\r\n", idx, size, handle);
    pkdata[idx].locker = 0x1;
    memcpy( (void *)pbuffer, (void *)pkdata[idx].pData, size);
    pkdata[idx].flag = 0x0;
    pkdata[idx].locker = 0x0;
    sem_post(&pkdata[idx].sem1);
    return size;
}

 
void *DiffMechInit(unsigned int size)
{
    void *ptr = (void *)malloc( sizeof (PKDATA_t) * size );
    if (ptr == 0)
    {
       printf("[DIFF_MECH] malloc error ,size=%d\r\n", size);
       return -1;
    }	

    PKDATA_t *pkdata = (PKDATA_t *)ptr;
	
    memset(ptr, 0, sizeof (PKDATA_t) * size);
	

    int idx;
    for (idx=0; idx<size; idx ++)
    {
	sem_init(&pkdata[idx].sem1, 0, 1); // 空闲的
        sem_init(&pkdata[idx].sem2, 0, 0); // 忙的
    }
 	//pthread_cond_init(&pkdata[idx].cond, NULL);
    printf("malloc diff mech init=%d\r\n", ptr);
    return (void *)ptr;
}

void init_sem()
{
    int idx;
    for (idx=0; idx<30; idx ++)
    {
        //sem_init(&pkdata[idx].sem1, 0, 1); // 空闲的
        //sem_init(&pkdata[idx].sem2, 0, 0); // 忙的
    }
}
#endif
BUFFERDATA_t *create_myfifo()
{
     BUFFERDATA_t *p = (BUFFERDATA_t *)malloc(sizeof (BUFFERDATA_t));
     return p;
}
static BUFFERDATA_t *phead_fifo;
static BUFFERDATA_t *ptail_fifo;
static BUFFERDATA_t *phead_audio;
void create_testfifo()
{
       phead_fifo = create_myfifo();
       phead_fifo->pNext = NULL;
       phead_fifo->size = 0;
      
       phead_audio = create_myfifo();
       phead_audio->pNext = NULL;
       phead_audio->size = 0;
       //ptail_fifo = phead_fifo;
       //ptail_fifo = create();
       //phead_fifo->pNext = ptail_fifo;
       //phead_fifo->pLast = NULL;
       //ptail_fifo->pLast = phead_fifo;
       //ptail_fifo->pNext = NULL;
}


extern BUFFERDATA_t *get_ele();
int add_ele(BUFFERDATA_t *ele)
{
      if (phead_fifo->size > 10)
      {
	 BUFFERDATA_t *pTMP = get_ele();
         if (pTMP != NULL)
         {
            free(pTMP->buf);
            free(pTMP);
         }
      }
      ele->pNext = phead_fifo->pNext;
      phead_fifo->pNext = ele;
      phead_fifo->size ++;
      //printf("add size=%d\r\n", ele->size);
      return 0;
}

BUFFERDATA_t *get_ele()
{
      BUFFERDATA_t *pTMP = phead_fifo;
      BUFFERDATA_t *pLAST = 0;
      while (pTMP->pNext != NULL)
      {
         pLAST= pTMP;
         pTMP = pTMP->pNext;
      }
 
      if (pTMP == phead_fifo)
	return NULL;
	
      pLAST->pNext = NULL;
      phead_fifo->size --;
      return pTMP; 
}

// for audio fifo
extern BUFFERDATA_t *get_audio();
int add_audio(BUFFERDATA_t *ele)
{
      if (phead_audio->size > 10)
      {
	 BUFFERDATA_t *pTMP = get_audio();
         if (pTMP != NULL)
         {
            free(pTMP->buf);
            free(pTMP);
         }
      }
      ele->pNext = phead_audio->pNext;
      phead_audio->pNext = ele;
      phead_audio->size ++;
      //printf("add size=%d\r\n", ele->size);
      return 0;
}

BUFFERDATA_t *get_audio()
{
      BUFFERDATA_t *pTMP = phead_audio;
      BUFFERDATA_t *pLAST = 0;
      while (pTMP->pNext != NULL)
      {
         pLAST= pTMP;
         pTMP = pTMP->pNext;
      }
 
      if (pTMP == phead_audio)
	return NULL;
	
      pLAST->pNext = NULL;
      phead_audio->size --;
      return pTMP; 
}






#ifdef _TEST_DIFFMECH_
int main(int argc, char **argv)
{
   	create_testfifo();
        int idx;
        for (idx=0; idx<100000; idx ++)
        {
            BUFFERDATA_t *pTMP = create_myfifo();
            pTMP->size = idx; 
	    add_ele(pTMP);
        }

	for (idx=0; idx<20; idx ++)
        {
            BUFFERDATA_t *p = get_ele();
            if (p != NULL)
	    printf("%d\r\n", p->size);   
        }
}
#endif
